C语言从无到有构建一个学生成绩管理系统 |
您所在的位置:网站首页 › c语言 录入学生的学号和成绩 › C语言从无到有构建一个学生成绩管理系统 |
#include //标准输入输出 #include //内存分配 #include /*####说明#### 简单学生管理系统 vc++6.0编译无error,无warning 已实现功能:添加学生,列出学生信息列表,删除学生,退出,学号重复检查,排序功能, 多科成绩录入(求平均成绩,及总平均成绩),保存记录,读取记录,修改功能; 待实现功能:查询...... 第一天、创建文件,开始编写,增加添加学生函数,增加列出学生函数,增加删除学生函数,退出 版本1.0 第二天、修改内容:增加学号重复检查函数,修复显示内容时程序终止,输出列表函数优化,添加学生函数优化 1.1 第三天、修改内容:增加排序函数,删除函数内部优化,main函数内部改动,添加学生函数优化 1.2 第四天、修改内容:增加多科目录入,添加函数优化,新增总成绩与平均成绩显示,排序函数优化,输出函数改动 1.3 第五天、修改内容:新增保存函数,读取函数,主程序修改,新增链表清除函数1.4 第六天、修改内容:新增修改函数,新增宏定义MAX_SCORE and MAX_SNO,方便程序的修改,修改程序中所有warning,一些bug修正1.5 */ //常量定义区+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #define bool int //由于C语言中不存在bool型,所以这里把它定义成int型 #define true 1 //同上 #define false 0 //↑ #define LEN sizeof(struct ryb) //动态内存分配空间大小 #define DATAFILE "DATAFILE.WL"//数据保存文件名 #define MAX_SCORE 150 //最高分数上限值 #define MAX_SNO 200 //最多录入学生上限值,即能输入的最大学号数 //END常量定义============================================================================================================ //声明函数================================================================================================================= struct ryb * del_item_ryb (struct ryb * head,int sno,int * del_message);//删除指定学号节点(链表头,欲删除学号,处理结果(1为删除成功,0为删除失败)),返回删除后的链表头 struct ryb * create_item_ryb (struct ryb * head);//向指定的链表添加学生,并返回链表头 void put_ryb (struct ryb * head);//输出学号及成绩(欲输出链表头) bool is_sno(struct ryb * head, int sno );//判断指定学号是否存在,如存在返回true,不存在返回false(链表头,欲判断学号) struct ryb * order(struct ryb * head, enum ordertype type, int fs );//排序函数;(链表头,排序方式(asc或desc),排序类型(1为按学号,2为按总成绩)) bool save_data(struct ryb * head);//保存链表数据函数(欲保存链表头) struct ryb * read_data(void);//读取数据到链表,并返回链表头 void clear(struct ryb * head);//清除函数,清除指定链表所有数据,释放内存空间 void amend_ryb(struct ryb * head, int sno);//修改函数,修改指定学号学生成绩信息(链表头,要修改成绩的学生学号) struct ryb { //定义链表数据结构 int sno; //学号 int chinese; //语文 int math; //数学 int english; //英语 int clanguage; //C语言 int tiyu; //体育 int score; //总成绩 struct ryb *next; }; enum ordertype{//定义排序枚举类型 asc,desc }; //性感的分割线$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$主程序$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ int main ( void ) { struct ryb * head,* temp_h;//链表头,临时链表 bool exit = false; short int value;//接受输入信息1,2,3,4 1表示添加信息,2显示信息,3删除信息,4排序,5退出 int sno, *del_message = 0;//学号,删除函数处理结果(1为删除成功,0为删除失败) int pxfs,pxlx;//排序方式,排序类型(方式asc\desc);(类型 1学号,2成绩) char is_quit;//表示是否退出,y或Y表示退出,否则不退出 char is_save;//表示是否保存数据,y或Y表示保存,否则不保存 char is_read;//表示是否读取数据,y或Y表示读取,否则不读取 bool ssave;//表示是否保存成功,true表示成功,false表示保存失败 int amend_sno; //表示要修改的学号 head = (struct ryb *) malloc(LEN);//创建初始链表 head->sno =0;//链表赋初值 head->next = NULL; do { printf("学生管理系统v1.5(C语言版)\n\n"); printf("①添加学生\n②显示成绩链表\n③删除学生\n④排序\n⑤保存数据\n⑥读取数据\n⑦修改\n⑧退出系统\n\n"); printf("等待命令输入:"); fflush(stdin);//清空键盘缓冲区 scanf("%d",&value); if(value == 1)//添加 { head = create_item_ryb(head);//添加信息 printf("录入信息结束!\n"); system("pause"); }else if (value == 2)//显示 { put_ryb(head); //显示信息 system("pause"); }else if(value == 3)//删除 { printf("请输入要删除的学生学号:"); fflush(stdin);//清空键盘缓冲区 scanf("%d",&sno); head = del_item_ryb(head,sno, del_message); //删除 if(*del_message == 1) { printf("删除成功!!!\n"); } else{ printf("删除失败!!!\n"); } system ("pause"); }else if(value == 4)//排序 { r: printf ("请请输入排序方式(1升序,2降序):"); fflush(stdin); scanf("%d",&pxfs); printf ("请输入排序类型(1按学号,2按成绩):"); fflush(stdin); scanf("%d",&pxlx); if (pxfs >2 || pxfs 2 || pxlx 0 && amend_sno sno==sno) { if(p == head)//如果第一个为要删除的值 { head = head->next;//修改链表头 //printf("已成功修改头指针sno=%d\n",head->sno); } else { p1->next = p->next;//将链表节点指向要删除的链表节点的下一节点 free(p);//释放已删除的链表节点内存 } *message = 1; break; } p1 = p;//保存当前链表节点 p = p->next; if(p->next==NULL) { *message = 0; } }while(p->next); return head; } #endif struct ryb * create_item_ryb (struct ryb * head) //向指定的链表添加学生,并返回链表头 { struct ryb *p1; int i=1;//i表示学生数 int tempsno;//临时学号 int scorearr[5],n;//分数数组,循环值 printf("提示:当学号为0时则终止添加,并返回主界面\n\n");//输出提示信息 p1 = head; while (p1->next != NULL)//寻找链表尾,找到后将p1指向链表尾以接受学生信息的添加 { p1 = p1->next; i++; } do { p1->sno = 0; sno: printf("请输入学生%d学号:",i); fflush(stdin);//清空键盘缓冲区 scanf("%d",&tempsno); if(tempsno != 0) { if (is_sno(head,tempsno) == false)//判断学号是否存在 { p1->sno = tempsno; } else { printf ("学号[%d]已存在!!!\n",tempsno); goto sno; } } else{ continue; } printf("---------------------------------------------\n"); printf("请输入学生%d成绩(语文,数学,英语,C语言,体育,以逗号分隔):",i); for(n=0;nsno == 0) { ; } else if(p1->sno < 1 || p1->sno > MAX_SNO)//判断学号是否合法,(1~200) { printf("学号输入不合法,学号为1-%d之间的数包括(1,%d)!!!\n",MAX_SNO,MAX_SNO); system("pause"); continue; }else//判断成绩合法性 { for(n=0;nsno = tempsno; p1->chinese = scorearr[0]; p1->math = scorearr[1]; p1->english = scorearr[2]; p1->clanguage = scorearr[3]; p1->tiyu = scorearr[4]; //求总成绩 p1->score=scorearr[0]+scorearr[1]+scorearr[2]+scorearr[3]+scorearr[4]; } if(p1->sno != 0) { p1->next = (struct ryb *) malloc(LEN);//create一个新节点给p1->next p1 = p1->next;//将新节点地址给p1 p1->next = NULL;//↑ }else{ p1->sno = 0; } i++; }while (p1->sno != 0);//判断学号是否为0;为0退出添加 return head; } #if(1) void put_ryb (struct ryb * head)//输出学号及成绩(欲输出链表头) { struct ryb *pryb = head; struct ryb zcj;//总成绩 int student_num = 0;//学生人数 //初始化总成绩结构体 zcj.chinese = 0; zcj.clanguage = 0; zcj.english = 0; zcj.math = 0; zcj.tiyu = 0; //初始化END system("cls"); printf (" --------------\n"); printf ("|某班学生成绩表|\n"); printf (" --------------\n"); printf (" ---- ---- ---- ---- ----- ---- ------ --------\n"); printf ("|学号| |语文| |数学| |英语| |C语言| |体育| |总成绩| |平均成绩|\n"); printf (" ---- ---- ---- ---- ----- ---- ------ --------\n");//8,8,8,8,9,8,10,12 do{ if(pryb->sno != 0)//输出成绩 { printf("%-8d%-8d%-8d%-8d%-9d%-8d%-10d%-12d\n",pryb->sno,pryb->chinese,pryb->math, pryb->english,pryb->clanguage,pryb->tiyu,pryb->score, pryb->score / 5); zcj.chinese = zcj.chinese + pryb->chinese ;//计算各科总成绩 zcj.clanguage = zcj.clanguage + pryb->clanguage ; zcj.english = zcj.english + pryb->english ; zcj.math = zcj.math + pryb->math ; zcj.tiyu = zcj.tiyu + pryb->tiyu ; student_num++;//记录总学生人数,表示链表不为空: pryb=pryb->next; } }while(pryb->next); if (student_num >= 1)//判断链表是否为空 { printf ("\n\n[总平均成绩]:(语文:%d,数学:%d,英语:%d,C语言:%d,体育:%d)\n",zcj.chinese/student_num, zcj.math / student_num, zcj.english / student_num, zcj.clanguage / student_num , zcj.tiyu / student_num);//输出总平均成绩 }else { printf ("没有可以输出列表!\n\n"); } } #endif bool is_sno(struct ryb * head,int sno)//判断学号是否存在(头指针,学号),如学号存在返回true,不存在返回false { struct ryb * p; p=head; do { if(p->sno == sno) { return true; } if (p->next != NULL) { p = p->next; } }while(p->next!=NULL); return false; } //排序函数 排序使用冒泡算法 struct ryb * order(struct ryb * head, enum ordertype type, int fs )//排序函数;(链表头,排序方式(asc或desc),排序类型(1为按学号,2为按总成绩)) { struct ryb *p,*rp,*ptemp,*rph;//要排序的链表,要返回的链表,临时排序链表,要返回的链表头 int max,min; int pro_mess;//删除函数处理结果1,0 if (head->sno == 0) { return head; } p = head; max = 0, min = 0; rp = (struct ryb *) malloc(LEN);//create一个新节点给rp rph = rp; do{ ptemp = p; if(fs == 1)//按学号 { max = ptemp->sno;//赋初值 min = ptemp->sno; } else { //按成绩 max = ptemp->sno; min = ptemp->score; max = ptemp->score; } rp->sno = ptemp->sno ; rp->score =ptemp->score ; rp->tiyu = ptemp->tiyu ; rp->english = ptemp->english ; rp->chinese = ptemp->chinese ; rp->math = ptemp->math ; rp->clanguage = ptemp->clanguage ; do{ if(type == desc)//降序 { if(fs == 1)//按学号 { if(ptemp->sno > max) { max = ptemp->sno; rp->sno = ptemp->sno ; rp->score =ptemp->score ; rp->tiyu = ptemp->tiyu ; rp->english = ptemp->english ; rp->chinese = ptemp->chinese ; rp->math = ptemp->math ; rp->clanguage = ptemp->clanguage ; } } else if (fs == 2)//按成绩 { if(ptemp->score > max) { max = ptemp->score; rp->sno = ptemp->sno ; rp->score = ptemp->score ; rp->tiyu = ptemp->tiyu ; rp->english = ptemp->english ; rp->chinese = ptemp->chinese ; rp->math = ptemp->math ; rp->clanguage = ptemp->clanguage ; } } } if(type == asc)//升序 { if(fs == 1)//按学号 { if(ptemp->sno < min) { min = ptemp->sno; rp->sno = ptemp->sno ; rp->score = ptemp->score ; rp->tiyu = ptemp->tiyu ; rp->english = ptemp->english ; rp->chinese = ptemp->chinese ; rp->math = ptemp->math ; rp->clanguage = ptemp->clanguage ; } } else if (fs == 2)//按成绩 { if(ptemp->score < min) { min = ptemp->score; rp->sno = ptemp->sno ; rp->score = ptemp->score ; rp->tiyu = ptemp->tiyu ; rp->english = ptemp->english ; rp->chinese = ptemp->chinese ; rp->math = ptemp->math ; rp->clanguage = ptemp->clanguage ; } } } ptemp= ptemp->next ; }while(ptemp->next != NULL); p=del_item_ryb(p,rp->sno, &pro_mess); rp->next = (struct ryb *) malloc(LEN);//create一个新节点给rp->next rp = rp->next ; if(p->next == NULL) {//添加链表尾信息 链表尾为一个指向NULL的空结构,以表示链表结束 rp->score = 0; rp->sno = 0; rp->next = NULL; } }while(p->next != NULL); return rph;//返回排序后链表头 } //排序函数END;------------------------------------------------------------------------------ bool save_data(struct ryb * head)//保存链表数据函数(欲保存链表头),成功返回true,失败返回false { FILE * fp; struct ryb * p; p = head; if (head->sno == 0)//如果链表为空 { return false;//返回false } fp = fopen(DATAFILE, "w+");//打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。 do{ fprintf(fp,"%d,%d,%d,%d,%d,%d,%d",p->sno ,p->chinese ,p->math ,p->english ,p->clanguage , p->tiyu ,p->score );//保存结构体并以|分隔 p = p->next;// if(p->sno != 0)//等于0表示链表结束 { fputc('|',fp);//|这里表示数据分段 }else{ fputc('&',fp);//&这里表示文本结束 } }while(p->sno != 0); fclose(fp);//关闭文件 return true; } //savedata_END------ struct ryb * read_data(void)//读取数据到链表,并返回链表头,失败返回 NULL { FILE * fp; struct ryb *head, *p; int n;//接收fscanf()返回值,以判断是否读取正确 char temp_ch;//临时字符,存放&或| head = (struct ryb *) malloc(LEN);//创建初始链表 p = head; fp = fopen(DATAFILE, "r");//以只读方式打开文件 if(fp == NULL)//判断文件是否打开失败 { return NULL; } while(1){ n = fscanf(fp,"%d,%d,%d,%d,%d,%d,%d",&p->sno ,&p->chinese ,&p->math ,&p->english , &p->clanguage ,&p->tiyu ,&p->score); if(n != 7) { printf ("数据读取过程中出错,数据读取失败!T_T\n"); system("pause"); clear(head); return NULL; } temp_ch = fgetc(fp); if(temp_ch == '|') { p->next = (struct ryb *)malloc(LEN); p = p->next ; } else { p->next = (struct ryb *)malloc(LEN); p = p->next ; p->sno = 0; p->next = NULL; break; } } return head; } //read_data.END------------------- void clear(struct ryb * head)//清除函数,清除指定链表所有数据,释放内存空间 { struct ryb * p; while(1) { if(head->sno == 0) { free(head);//释放空间 break; } else{ p=head; head = head->next ; free(p); } } } //clear.END------------------------------------------------------------ void amend_ryb(struct ryb * head, int sno)//成绩修改函数,修改指定学号学生成绩信息(链表头,要修改成绩的学生学号) { struct ryb *p;//链表 int arr[5],retvalue,i;//临时成绩数组[语,数,英,C语言,体育],scanf返回值,i循环用 p = head; if (is_sno(head,sno) == false)//判断要修改的学生是否存在 { printf("您要修改的学号[%d]不存在!(?_?)\n",sno); system("pause"); return; } while (1) { if(p->sno == sno) { flag: printf("当前要修的学生学号为[%d],成绩:\n[语文:%d],[数学:%d],[英语:%d],[C语言:%d],[体育:%d],[总成绩:%d]\n\n", sno,p->chinese,p->math,p->english,p->clanguage,p->tiyu,p->score); printf("提示:各科成绩用逗号隔开,输入-1即表示不修改该科目成绩!↖(^ω^)↗\n"); printf ("请输入新的成绩[语,数,英,C语言,体育]:"); fflush(stdin); retvalue = scanf("%d,%d,%d,%d,%d",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4]); if (retvalue == 5) { for(i=0;ichinese = arr[0]; } if(arr[1] != -1) { p->math = arr[1]; } if(arr[2] != -1) { p->english = arr[2]; } if(arr[3] != -1) { p->clanguage = arr[3]; } if(arr[4] != -1) { p->tiyu = arr[4]; } p->score = p->chinese + p->math + p->english + p->clanguage + p->tiyu;//计算修改过的总成绩 printf ("修改完毕!^_^\n"); system ("pause"); return; } else{ printf ("你输入的的值有误,请重新输入!→_→\n"); system("pause"); goto flag; } } } } |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |